#include "chip_ts32xx_hal_gpio.h"

unsigned short CrcModbus16(unsigned char *data_value,
                           unsigned char data_length) {
  int i;
  unsigned short crc_value = 0xffff;
  while (data_length--) {
    crc_value ^= *data_value++;
    for (i = 0; i < 8; i++) {
      if (crc_value & 0x0001)
        crc_value = (crc_value >> 1) ^ 0xA001;
      else
        crc_value = crc_value >> 1;
    }
  }
  return (crc_value);
}

bool HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    return (bool)(0 != ((GPIOx->BSR) & GPIO_Pin));
}

void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
    if (PinState)
    {
        GPIOx->BSR = (u16)GPIO_Pin;
    }
    else
    {
        GPIOx->BSR = (u32)GPIO_Pin << 16;
    }
}

void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->TGL = GPIO_Pin;
}

void HAL_TimerInit(unsigned char WhichTimer, u16 Period, unsigned char Psc, u8 Priority)
{
    #if 1
    switch (WhichTimer)
    {
    case TIM0_ENUM:
        ll_timer_cnt_set_us(TIM0, Period);
        ll_timer_cnt_start(TIM0);
        NVIC_EnableIRQ(TIM0_IRQn);
        break;
    case TIM1_ENUM:
        ll_timer_cnt_set_us(TIM1, Period);
        ll_timer_cnt_start(TIM1);
        NVIC_EnableIRQ(TIM1_IRQn);
        break;
    case TIM4_ENUM:
        ll_timer_cnt_set_us(TIM4, Period);
        ll_timer_cnt_start(TIM4);
        NVIC_EnableIRQ(TIM4_IRQn);
        break;
    default:
        ll_timer_cnt_set_us(TIM0, Period);
        ll_timer_cnt_start(TIM0);
        NVIC_EnableIRQ(TIM0_IRQn);
        break;
    }
    #else
    TYPE_LL_TIMER_INIT timer_init;
    TYPE_LL_TIMER_CNT_CFG cnt_cfg;

    timer_init.prescaler = (TYPE_ENUM_LL_TIMER_PSC)(Psc);
    timer_init.timer_src_sel = LL_TIMER_SRC_SYS_RISING;

    cnt_cfg.count_initial = 0;
    cnt_cfg.count_period = Period; // 48Mhz*125us = 6000
    cnt_cfg.count_ie = ENABLE;

    NVIC_InitTypeDef nvic; //ʹ��TIMER0�ж�
    switch (WhichTimer)
    {
    case TIM0_ENUM:
        ll_timer_init(TIMER0, &timer_init);
        ll_timer_cnt_mode_config(TIMER0, &cnt_cfg);
        ll_timer_start(TIMER0, LL_TIMER_MODE_SEL_COUNTER);
        nvic.NVIC_IRQChannel = TIM0_IRQn;
        break;
    case TIM1_ENUM:
        ll_timer_init(TIMER1, &timer_init);
        ll_timer_cnt_mode_config(TIMER1, &cnt_cfg);
        ll_timer_start(TIMER1, LL_TIMER_MODE_SEL_COUNTER);
        nvic.NVIC_IRQChannel = TIM1_IRQn;
        break;
    case TIM4_ENUM:
        ll_timer_init(TIMER4, &timer_init);
        ll_timer_cnt_mode_config(TIMER4, &cnt_cfg);
        ll_timer_start(TIMER4, LL_TIMER_MODE_SEL_COUNTER);
        nvic.NVIC_IRQChannel = TIM4_IRQn;
        break;
    default:
        ll_timer_init(TIMER0, &timer_init);
        ll_timer_cnt_mode_config(TIMER0, &cnt_cfg);
        ll_timer_start(TIMER0, LL_TIMER_MODE_SEL_COUNTER);
        nvic.NVIC_IRQChannel = TIM0_IRQn;
        break;
    }

    nvic.NVIC_IRQChannelPriority = Priority;
    nvic.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic);
    #endif
}

//flash relation
bool need_lvd = false;
#define DATA_LEN 32
u8 flash_data[DATA_LEN] __attribute__((aligned(4)));
u32 eflash_addr = EFLASH_DATA_SEC_INDEX * LL_EF_SECTOR_SIZE;
void EFlashInit(void)
{
    TYPE_LL_EFLASH_INIT eflash_init;
    ll_eflash_init(EFLASH, &eflash_init);
    need_lvd = true;
    NVIC_InitTypeDef nvic;
    (void)nvic; //disable warning
    // nvic.NVIC_IRQChannel = LVD_IRQn;
    // nvic.NVIC_IRQChannelPriority = 0;
    // nvic.NVIC_IRQChannelCmd = ENABLE;
    // NVIC_Init(&nvic);
}


//CRC只能写到。。。
void WriteData(bool isValidData)
{
	// flash_data[0]++;

	unsigned short Crc = CrcModbus16(flash_data, (DATA_LEN - 4));
    if(false == isValidData){
        Crc++;
    }
	flash_data[DATA_LEN - 4] = 0xFF & (Crc);
	flash_data[DATA_LEN - 3] = 0xFF & (Crc >> 8);
	ll_eflash_erase_one_sector(EFLASH, EFLASH_DATA_SEC_INDEX);
	ll_eflash_auto_program(EFLASH, eflash_addr, (u32)flash_data, sizeof(flash_data));
}

bool ReadData()
{
	u16 i = 0;
	u32 *pBuf = (u32 *)flash_data;
	for (i = 0; i < (sizeof(flash_data)); i += 4)
	{
		*pBuf++ = LL_EFLASH_DATA_GET(eflash_addr + i);
	}
	unsigned short Crc = CrcModbus16(flash_data, (DATA_LEN - 4));
	unsigned short DataCrc = (flash_data[DATA_LEN - 3] << 8) | (0xFF & flash_data[DATA_LEN - 4]);
	if (Crc != DataCrc){
        return false;
	}
    else {
	    return true;
    }
}
//flash relation end




















void LVDInit(void)
{
    #if 0
    SYSCTRL_REG_OPT(
        LVD->LVD_CON &= ~(LL_LVD_CON_LVD_OE);
        LVD->LVD_CON = (LVD->LVD_CON & ~(LL_LVD_CON_VDD_DBS_LO_LIMIT(ALL_BYTE_FF))) | LL_LVD_CON_VDD_DBS_LO_LIMIT(10);
        LVD->LVD_CON = (LVD->LVD_CON & ~(LL_LVD_CON_VDD_DBS_HI_LIMIT(ALL_BYTE_FF))) | LL_LVD_CON_VDD_DBS_HI_LIMIT(10);
        LVD->LVD_CON = (LVD->LVD_CON & ~(LL_LVD_CON_VCC_LVD_SET(ALL_BYTE_FF))) | LL_LVD_CON_VCC_LVD_SET(LL_LVD_VCC_LVD_SET_2_7);
        LVD->LVD_CON &= ~(LL_LVD_CON_VCC_RST_EN);
        LVD->LVD_CON |= (LL_LVD_CON_VCC_LVD_EN | LL_LVD_CON_VDD_LVD_EN | LL_LVD_CON_VDD_RST_EN | LL_LVD_CON_LVD_OE);
        LL_LVD_VCC_PENDING_CLR(LVD);
        LL_LVD_VDD_PENDING_CLR(LVD);)

    NVIC_InitTypeDef nvic;
    nvic.NVIC_IRQChannel = LVD_IRQn;
    nvic.NVIC_IRQChannelPriority = 0;
    nvic.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic);
    #else

    SYSCTRL_REG_OPT(
    LVD->LVD_CON &= ~(LL_LVD_CON_LVD_DIG_EN);
    LVD->LVD_CON =  (LVD->LVD_CON & ~(LL_LVD_CON_VDD_DBS_LO_LIMIT(ALL_BYTE_FF))) | LL_LVD_CON_VDD_DBS_LO_LIMIT(10);
    LVD->LVD_CON =  (LVD->LVD_CON & ~(LL_LVD_CON_VDD_DBS_HI_LIMIT(ALL_BYTE_FF))) | LL_LVD_CON_VDD_DBS_HI_LIMIT(10);
    LVD->LVD_CON1 =  (LVD->LVD_CON1 & ~(LL_LVD_CON1_VCC_DBS_LO_LIMIT(ALL_BYTE_FF))) | LL_LVD_CON1_VCC_DBS_LO_LIMIT(10);
    LVD->LVD_CON1 =  (LVD->LVD_CON1 & ~(LL_LVD_CON1_VCC_DBS_HI_LIMIT(ALL_BYTE_FF))) | LL_LVD_CON1_VCC_DBS_HI_LIMIT(10);
    LVD->LVD_CON =  (LVD->LVD_CON & ~(LL_LVD_CON_VCC_LVD_SET(ALL_BYTE_FF))) | LL_LVD_CON_VCC_LVD_SET(LL_LVD_VCC_LVD_SET_3_6);
    LVD->LVD_CON &= ~(LL_LVD_CON_VCC_RST_EN);
    LVD->LVD_CON |= (LL_LVD_CON_VCC_LVD_EN| LL_LVD_CON_VDD_LVD_EN | LL_LVD_CON_VDD_RST_EN | LL_LVD_CON_LVD_DIG_EN);
    LL_LVD_VCC_PENDING_CLR(LVD);
    LL_LVD_VDD_PENDING_CLR(LVD);
    )
    
    NVIC_InitTypeDef nvic;
    nvic.NVIC_IRQChannel = LVD_IRQn;
    nvic.NVIC_IRQChannelPriority = 0;
    nvic.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic);


    #endif
}
